namespace devtm.Aop.Emit
{
    using System;
    using Mono.Cecil.Cil;
    using Mono.Cecil;


    [Serializable]
    public class EmitMethodInvokeExpression : EmitExpression
    {



        public EmitMethodInvokeExpression()
        {
            this.args = new EmitExpressionCollection();
        }


        public EmitMethodInvokeExpression(EmitExpression targetObject, params EmitExpression[] args)
        {
            this.args = new EmitExpressionCollection();
            this.TargetObject = targetObject;
            this.args.AddRange(args);
        }

        
        public EmitExpression TargetObject { get; set; }
        public EmitExpressionCollection args { get; private set; }


        public override void Compile(CilWorker gen)
        {           

            EmitMethodReferenceExpression m = TargetObject as EmitMethodReferenceExpression;            

            if (m.TargetObject == null || m.TargetObject is EmitBaseReferenceExpression)
            {

                if (m.TargetObject is EmitBaseReferenceExpression)
                    m.TargetObject.Compile(gen);

                foreach (EmitExpression item in args)
                {
                    item.UserData.Add("way", "get");
                    item.Compile(gen);
                    item.UserData.Remove("way");
                }

                gen.Insert(OpCodes.Call, m.Method);

                }
            else
            {

                m.TargetObject.UserData.Add("way", "get");
                m.TargetObject.Compile(gen);
                m.TargetObject.UserData.Remove("way");


                foreach (EmitExpression item in args)
                {
                    item.UserData.Add("way", "get");
                    item.Compile(gen);
                    item.UserData.Remove("way");
                }

                
                gen.Insert(OpCodes.Callvirt, m.Method);

            }    
            
            //gen.Insert(OpCodes.Calli, Method);


        }

                    


    }
}
